# -*- coding: utf-8 -*-
"""
Created on Wed Jan  6 10:48:58 2021

@author: 98330
"""
import numpy as np
import math

class ServerSwitchBasic():
 
 
    def __init__(self, location_array, k_near):
        self.location_array = location_array
        self.k_near = k_near
       
        
       
    def calc_distance(self, lat_a, lng_a, lat_b, lng_b):
        """calculate the actual distance between location_a and location_b
        
        param
        ----------
            lat_a : float
                lantitude of the location_a
            lng_a : float
                longitude of the location_a
            lat_b : float
                lantitude of the location_b
            lng_b : float
                longitude of the location_b
                
        return
        ----------
            12742 * math.asin(math.sqrt(a)) : float
                the distance information between the two location
        
        refer
        ----------
            Other func : None
        """
        p = 0.017453292519943295 
        
        a = (0.5 - math.cos((lat_b - lat_a) * p) / 2 + math.cos(lat_a * p) * math.cos(lat_b * p) 
        * (1 - math.cos((lng_b - lng_a) * p)) / 2)
        return 12742 * math.asin(math.sqrt(a)) 

    def array_calculate_distance(self,location_a, location_b):
        """calculate the actual distance between the element in loca_a and loca_b
        
        param
        ----------
            location_a : list
                store all the location information in first location_list
            location_b :list
                store all the location information in second location_list
               
        return
        ----------
            12742 * np.arcsin(np.sqrt(a)) : list
                store all the distance information between the elements in the two lists
        
        refer
        ----------
            Other func : None
        """
        p = 0.017453292519943295
        
        a = (0.5 - np.cos((location_b[:,0] - location_a[:,0]) * p) / 2 + np.cos(location_a[:,0] * p) 
        * np.cos(location_b[:,0] * p) * (1 - np.cos((location_b[:,1] - location_a[:,1]) * p)) / 2)
        return 12742 * np.arcsin(np.sqrt(a))
    
    def location_divide(self):
        """find the near k base_station and get their index
        
        param
        ----------
            location_array : array
                the array to store both the lantitude and longtitude information of the location
                structure : nx2
                content : first column ---> lantitude , second column ---> longitude
            k_near : int
                the number of the near base station we will find
        
        return
        ----------
            list_near : list
                store the k near base stations of each base
                structure : [[content1],[content2],.......,[contentn]]
                content : [] ---> the index of the k near base stations
            list_far : list
                store the other base stations of each base
                structure : [[content1],[content2],.......,[contentn]]
                content : [] ---> the index of the other base stations
            list_assign : list
                store the index of which station provide the flow to one base station
                structure : [[content1],[content2],.......,[contentn]]
                content : [] ---> the indexes of base stations that share the flows to one base station according to the index
        
        refer
        ----------
            Other func :  self.array_calculate_distance
        """
        base_num = len(self.location_array)
        list_near = list()
        list_far = list()
        list_assign = []
            
        for i in range(base_num):
            list_assign.append([])
                
        for index in range(base_num):
            base_index = self.location_array[index]
            base_all = np.ones((base_num, 1)) * base_index
            base_distance = self.array_calculate_distance(base_all, self.location_array)
            distance_sort_index = np.argsort(base_distance)
            distance_near = list(distance_sort_index[0 : self.k_near])
            distance_far = list(distance_sort_index[self.k_near : base_num])
            list_near.append(distance_near)
            list_far.append(distance_far)
            for i in range(self.k_near):
                list_assign[distance_near[i]].append(index)
        return list_near, list_far, list_assign
    
    def server_switch(self):
        pass